package com.woniu.user.service.impl;

import com.woniu.user.constant.UserRedisKey;
import com.woniu.user.dto.AddressDTO;
import com.woniu.user.pojo.Address;
import com.woniu.user.mapper.AddressMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.user.service.IAddressService;
import com.woniu.user.vo.AddressVO;
import com.woniu.user.vo.UserLoginVO;
import lombok.SneakyThrows;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 地址表 服务实现类
 * </p>
 *
 * @author hushunlai
 * @since 2023-05-22
 */
@Service
public class AddressServiceImpl extends ServiceImpl<AddressMapper, Address> implements IAddressService {

    @Autowired(required = false)
    private AddressMapper addressMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public List<AddressVO> listAddress(UserLoginVO userLoginVO) {
        List<AddressVO> addressVOList;

        addressVOList = redisTemplate.boundListOps(UserRedisKey.USER_ADDRESS + userLoginVO.getMobile()).range(0, -1);
        if (addressVOList.size() != 0) {
            return addressVOList;
        }

        addressVOList = addressMapper.listAddress(userLoginVO.getId());

        for (AddressVO addressVO : addressVOList) {
            redisTemplate.boundListOps(UserRedisKey.USER_ADDRESS + userLoginVO.getMobile()).leftPush(addressVO);
        }
        redisTemplate.expire(UserRedisKey.USER_ADDRESS + userLoginVO.getMobile(), UserRedisKey.USER_ADDRESS_OUT_TIME, TimeUnit.HOURS);


        return addressVOList;
    }

    /**
     * @param addressDTO
     * @param userLoginVO
     * @return 两种情况：
     * 1.用户添加的是默认地址 覆盖redis 新增数据库
     * 2.用户添加的不是默认地址 新增数据库
     */
    @Override
    public Boolean addAddress(AddressDTO addressDTO, UserLoginVO userLoginVO) {

        Boolean flag = addressMapper.addAddress(addressDTO, userLoginVO.getId());

        reversalAddress(userLoginVO, addressDTO);

        return flag;
    }

    /**
     * @param addressDTO
     * @param userLoginVO
     * @return 四种情况：
     * 1.默认地址修改后还是默认地址，修改数据库，覆盖redis
     * 2.默认地址修改后是普通地址，修改数据库，删除redis
     * 3.普通地址修改后是默认地址，修改数据库，新增redis
     * 4.普通地址修改后还是普通地址，修改数据库
     */

    @Override
    public Boolean updateAddress(AddressDTO addressDTO, UserLoginVO userLoginVO) {

        //修改数据库中的地址
        Boolean flag = addressMapper.updateAddress(addressDTO, userLoginVO.getId());

        //普通地址修改后还是普通地址
        if (addressDTO.getIsDefault() == UserRedisKey.ISNOT_DEFAULT) {
            return flag;
        }

        //如果修改是将默认地址修改为普通地址 删除redis中的默认地址
        if (addressDTO.getIsDefault() == UserRedisKey.ISNOT_DEFAULT) {
            redisTemplate.boundHashOps(UserRedisKey.DEFAULT_ADDRESS).delete(userLoginVO.getMobile());
        } else { //如果修改是将普通地址修改为默认地址
            redisTemplate.boundHashOps(UserRedisKey.DEFAULT_ADDRESS).put(userLoginVO.getMobile(), addressDTO);
        }

        reversalAddress(userLoginVO, addressDTO);

        return flag;
    }

    @SneakyThrows
    private void reversalAddress(UserLoginVO userLoginVO, AddressDTO addressDTO) {

        //延时双删
        redisTemplate.opsForList().trim(UserRedisKey.USER_ADDRESS + userLoginVO.getMobile(), 1, 0);

        //查询该用户的所有地址
        List<AddressVO> addressVOList = listAddress(userLoginVO);

        List<AddressVO> collect = addressVOList.stream().filter(addressVO -> addressVO.getIsDefault() == 1).collect(Collectors.toList());

        //判断是否会出现两个默认地址，如果会，将新修改的默认地址变为默认地址，原来的地址取消默认地址
        if (collect.size() > 1) {
            //遍历两个默认地址 取出原来的默认地址 设置为普通地址
            for (AddressVO addressVO : collect) {
                if (addressVO.getId() != addressDTO.getId()) {
                    addressVO.setIsDefault((byte) 0);
                    BeanUtils.copyProperties(addressVO, addressDTO);
                    addressMapper.updateAddress(addressDTO, userLoginVO.getId());
                    break;
                }
            }
        }

        AddressVO addressVO = addressMapper.getDefaultAddress(userLoginVO.getId());
        redisTemplate.boundHashOps(UserRedisKey.DEFAULT_ADDRESS).put(userLoginVO.getMobile(), addressVO);

        //延时双删
        Thread.sleep(UserRedisKey.DELAY);
        redisTemplate.opsForList().trim(UserRedisKey.USER_ADDRESS + userLoginVO.getMobile(), 1, 0);

        listAddress(userLoginVO);
    }

    /**
     * @param addressDTO
     * @param userLoginVO
     * @return 两种情况：
     * 1.删除默认地址
     * 2.删除普通地址
     */
    @Override
    public Boolean deleteAddress(AddressDTO addressDTO, UserLoginVO userLoginVO) {

        Boolean flag = addressMapper.deleteAddress(addressDTO.getId(), userLoginVO.getId());

        if (addressDTO.getIsDefault() == UserRedisKey.IS_DEFAULT) {
            redisTemplate.boundHashOps(UserRedisKey.DEFAULT_ADDRESS).delete(userLoginVO.getMobile());
        }

        return flag;
    }

    @Override
    public AddressVO getDefaultAddress(String mobile) {
        AddressVO addressVO = (AddressVO)redisTemplate.boundHashOps(UserRedisKey.DEFAULT_ADDRESS).get(mobile);
        return addressVO;
    }

    @Override
    public Address getAddress(Integer addressId, String mobile) {

        AddressVO addressVO = (AddressVO) redisTemplate.boundHashOps(UserRedisKey.DEFAULT_ADDRESS).get(mobile);
        if (addressVO != null && addressId == addressVO.getId()) {
            Address address = new Address();
            BeanUtils.copyProperties(addressVO, address);
            return address;
        }

        Address address = addressMapper.getAddress(addressId);
        return address;
    }
}
